package cn.icanci.loopstack.plugin.dalgen.factory;

import cn.icanci.loopstack.plugin.dalgen.config.GlobalConfig;
import cn.icanci.loopstack.plugin.dalgen.model.ConfigurationInfoVO;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

import org.apache.commons.lang3.StringUtils;

/**
 * 配置文件解析器
 *
 * @author icanci
 * @since 1.0 Created in 2022/05/13 17:36
 */
public class PropertiesFactory {
    /**
     * 默认配置资源文件
     */
    public static String DEFAULT_CONFIG_FILE = "cs-gen.properties";

    /**
     * 加载配置文件
     * 
     * @param resource 资源文件名字
     * @throws IOException IOException
     */
    public static void loadProperties(String resource) throws IOException {
        DEFAULT_CONFIG_FILE = resource;
        loadProperties();
    }

    /**
     * 加载配置文件
     * 
     * @throws Exception 异常
     */
    public static void loadProperties() throws IOException {
        // 兼容Jar包外 处理配置文件
        InputStream inStream = PropertiesFactory.class.getClassLoader().getResourceAsStream(DEFAULT_CONFIG_FILE);
        if (inStream == null) {
            inStream = new FileInputStream(DEFAULT_CONFIG_FILE);
            if (inStream == null) {
                throw new RuntimeException("资源: " + DEFAULT_CONFIG_FILE + " 不存在");
            }
        }
        Properties prop = new Properties();

        prop.load(inStream);

        // 数据验证
        validate(prop);

        // 构建配置对象
        ConfigurationInfoVO infoVO = buildConfigurationInfo(prop);

        GlobalConfig.setGlobalConfig(infoVO);
    }

    /**
     * 构建配置对象
     * 
     * @param prop prop
     * @return 返回配置对象
     */
    private static ConfigurationInfoVO buildConfigurationInfo(Properties prop) {
        ConfigurationInfoVO infoVO = new ConfigurationInfoVO();
        infoVO.setDataBase(prop.getProperty(ConfigKVEnum.DATABASE.getKey()));
        infoVO.setDriver(prop.getProperty(ConfigKVEnum.DRIVER.getKey()));
        infoVO.setConnectUrl(prop.getProperty(ConfigKVEnum.CONNECT_URL.getKey()));
        infoVO.setLoginName(prop.getProperty(ConfigKVEnum.LOGIN_NAME.getKey()));
        infoVO.setPassword(prop.getProperty(ConfigKVEnum.PASSWORD.getKey()));
        infoVO.setInclude(prop.getProperty(ConfigKVEnum.INCLUDE.getKey()));
        infoVO.setIncludeMap(parseInclude(infoVO.getInclude()));
        infoVO.setCustomHandleInclude(prop.getProperty(ConfigKVEnum.CUSTOM_HANDLE_INCLUDE.getKey()));
        infoVO.setCustomHandleIncludeMap(parseInclude(infoVO.getCustomHandleInclude()));
        infoVO.setProjectPath(prop.getProperty(ConfigKVEnum.PROJECT_PATH.getKey()));
        infoVO.setAuthorName(prop.getProperty(ConfigKVEnum.AUTHOR_NAME.getKey()));
        String removePre = prop.getProperty(ConfigKVEnum.REMOVE_PRE_TABLE.getKey());
        infoVO.setRemovePreTable(removePre);
        infoVO.setRemovePreTables(buildRemovePreTables(removePre));
        String dbModule = prop.getProperty(ConfigKVEnum.DB_MODULE.getKey());
        infoVO.setDbModule(dbModule);
        String packageName = prop.getProperty(ConfigKVEnum.PACKAGE_NAME.getKey());
        if (StringUtils.isBlank(dbModule)) {
            infoVO.setPackageName(packageName);
        } else {
            infoVO.setPackageName(packageName + "." + dbModule);
        }

        // 解析项目目录地址 获取项目路径
        String appPath = System.getProperty("maven.user.dir");

        String projectPath = infoVO.getProjectPath();
        if (StringUtils.isBlank(projectPath)) {
            infoVO.setRealProjectCodePath(appPath);
        } else {
            while (projectPath.endsWith(File.separator)) {
                projectPath = projectPath.substring(0, projectPath.length() - 1);
            }
            infoVO.setRealProjectCodePath(appPath + File.separator + projectPath);
        }
        return infoVO;
    }

    /**
     * 进行分隔
     * 
     * @param removePre removePre
     * @return 分隔之后
     */
    private static Set<String> buildRemovePreTables(String removePre) {
        Set<String> set = new HashSet<>();
        if (StringUtils.isBlank(removePre)) {
            return set;
        }
        String[] split = removePre.split(";");
        for (String s : split) {
            if (StringUtils.isBlank(s)) {
                continue;
            }
            set.add(s);
        }
        return set;
    }

    /**
     * 数据验证
     *
     * @param prop prop
     */
    private static void validate(Properties prop) {
        Set<String> keys = ConfigKVEnum.getKeys();
        for (String key : keys) {
            String value = prop.getProperty(key);
            ConfigKVEnum enumByKey = ConfigKVEnum.getEnumByKey(key);
            if (enumByKey != null && !enumByKey.isMust()) {
                continue;
            }

            if (!StringUtils.isBlank(value)) {
                continue;
            }
            throw new RuntimeException("Key: " + key + " can not be null");
        }
    }

    /***
     * 解析需要构造的表Map方法
     * 
     * @param include include
     * @return 构造返回结果
     */
    private static Map<String, String> parseInclude(String include) {
        Map<String, String> result = new HashMap<>();
        if (StringUtils.isBlank(include)) {
            return result;
        }

        String[] strings = include.split(";");
        for (String key : strings) {
            if (StringUtils.isBlank(key)) {
                continue;
            }
            result.put(key, key);
        }

        return result;
    }
}
